////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Microsoft Corporation.  All rights reserved.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "tinyhal.h"
#include "..\..\..\..\DeviceCode\Targets\Native\FM3\DeviceCode\FM3.h"
//#include "mcu.h"

//#define INSERT_NOP
#define INSERT_WAIT
#define LCD_WAIT    200

#define LCD_ADDRESS (*(volatile unsigned short*)0x61000000)
#define LCD_VALUE   (*(volatile unsigned short*)0x61000002)

#define RS_LO   (FM3_GPIO->PDOR3 &= 0xBFFF;)
#define RS_HI   (FM3_GPIO->PDOR3 |= 0x4000;)

void P16_Initialize(void)
{
    // Reset
    FM3_GPIO->PFR9 &= 0xFFFE;   // P90 GPIO
    FM3_GPIO->DDR9 |= 0x0001;   // P90 output
    // RS
    FM3_GPIO->PFR3 &= 0xBFFF;   // P3E GPIO
    FM3_GPIO->DDR3 |= 0x4000;   // P3E output
}

void LCD_nRESET(int n)
{
    if (n)
        FM3_GPIO->PDOR9 |= 0x0001;
    else
        FM3_GPIO->PDOR9 &= 0xFFFE;
}

void P16_LCD_cmd(volatile unsigned short index, volatile unsigned short data)
{
    FM3_GPIO->PDOR3 &= 0xBFFF;
    LCD_ADDRESS = index;
#ifdef INSERT_WAIT
    volatile unsigned int n;
    for (n=0;n<LCD_WAIT;n++);
#endif
#ifdef INSERT_NOP
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
#endif
    FM3_GPIO->PDOR3 |= 0x4000;
    LCD_VALUE = data;
#ifdef INSERT_WAIT
    for (n=0;n<LCD_WAIT;n++);
#endif
#ifdef INSERT_NOP
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
#endif
    return;
}

void P16_LCD_index(volatile unsigned short index)
{
    FM3_GPIO->PDOR3 &= 0xBFFF;
    LCD_ADDRESS = index;
#ifdef INSERT_WAIT
    volatile unsigned int n;
    for (n=0;n<LCD_WAIT;n++);
#endif
#ifdef INSERT_NOP
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
#endif
    FM3_GPIO->PDOR3 |= 0x4000;
    return;
}

void P16_LCD_dat(volatile unsigned short data)
{
    LCD_VALUE = data;
#ifdef INSERT_NOP
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
#endif
    return;
}

unsigned short P16_LCD_read_dat(volatile unsigned short index)
{
    volatile unsigned short data;
    FM3_GPIO->PDOR3 &= 0xBFFF;
    LCD_ADDRESS = index;
#ifdef INSERT_WAIT
    volatile unsigned int n;
    for (n=0;n<LCD_WAIT;n++);
#endif
#ifdef INSERT_NOP
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
#endif
    FM3_GPIO->PDOR3 |= 0x4000;
    data = LCD_VALUE;
#ifdef INSERT_NOP
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
    __asm__ __volatile__("nop");
#endif
    return data;
}
//--//
